Design Stock Brokerage System

Last Updated: December 19, 2025

Ashish

Ashish Pratap Singh

hard

In this chapter, we will explore the low-level design of an online stock exchange system in detail.

Lets start by clarifying the requirements:

1. Clarifying Requirements

Before starting the design, it's important to ask thoughtful questions to uncover hidden assumptions and better define the scope of the system.

Here is an example of how a conversation between the candidate and the interviewer might unfold:

After gathering the details, we can summarize the key system requirements.

1.1 Functional Requirements

  • Each user must have an account with a cash balance and a portfolio of owned stocks.
  • Support trading of multiple stock symbols
  • Allow users to place limit and market orders (buy or sell)
  • Allow users to cancel pending (unmatched) orders
  • Users should be notified of status updates for their orders.
  • Users should be able to subscribe to stock price updates and receive notifications when the price changes.
  • Before placing an order, the system must validate it (e.g., check for sufficient funds for a buy order or sufficient stock quantity for a sell order).

1.2 Non-Functional Requirements

  • Concurrency: The system must be thread-safe to handle concurrent requests from multiple users placing orders simultaneously. 
  • Modularity: The system should be designed using object-oriented principles, with clear separation of concerns between components like accounts, orders, and the matching engine.
  • Extensibility: The design should be modular and easy to extend. For instance, adding new order types (e.g., Stop-Loss) or different notification channels (e.g., SMS, Email) should not require major refactoring.
  • Simplicity: The system should provide a simple, high-level interface for clients to perform common actions like placing an order, without exposing the underlying complexity of the matching engine.

2. Identifying Core Entities

Core entities are the fundamental building blocks of our system. We identify them by analyzing key nouns (e.g., user, stock, order, order book, trade) and actions (e.g., place, match, cancel, publish, view) from the functional requirements. These typically translate directly into classes, enums, or interfaces in an object-oriented design.

Let’s walk through the functional requirements and extract the relevant entities:

1. Manage user accounts, cash balances, and stock portfolios.

This points to a User entity as the primary actor. Each User has an Account, which is responsible for managing their cash balance and a portfolio of owned stocks. The stocks themselves are represented by a Stock entity, which includes a symbol and a market price.

2. Requirement: Allow users to place Market and Limit orders for buying and selling.

An Order is a central entity representing a user's intent to trade. Key attributes like OrderType (MARKET, LIMIT), TransactionType (BUY, SELL), and OrderStatus (OPEN, FILLED) are best represented by Enums.

3. A central engine must match buy and sell orders.

The core matching logic is encapsulated in a StockExchange entity. This class acts as the central marketplace, holding the order books for all stocks. It is implemented as a Singleton to ensure there is only one exchange in the system.

4. Provide a simple, high-level interface for the entire system.

To hide the complexity of the underlying components (matching engine, state transitions, command execution), a StockBrokerageSystem class is introduced. It acts as a Facade and Singleton, providing a unified entry point for all client interactions.

These core entities define the essential abstractions of an online stock exchange and will guide the structure of your low-level design and class diagrams.

3. Designing Classes and Relationships

This section breaks down the system's architecture into its fundamental classes, their responsibilities, and the relationships that connect them. We also explore the key design patterns that provide robustness and flexibility to the solution.

3.1 Class Definitions

Enums

Enums
  • OrderType: Distinguishes between MARKET and LIMIT orders.
  • TransactionType: Indicates whether an order is a BUY or SELL transaction.
  • OrderStatus: Tracks the lifecycle of an order (OPEN, FILLED, CANCELLED).

Data Classes

Account

A thread-safe class that holds a user's cash balance and their portfolio of stocks.

Account

It provides synchronized methods for debiting/crediting funds and adding/removing stocks.

Stock

Represents a publicly traded stock.

Stock

It holds the stock's symbol and its current market price. It also acts as the Subject in the Observer pattern, maintaining a list of observers to notify upon price changes.

Core Classes

User

Represents a client of the brokerage.

User

It holds an Account and acts as a concrete Observer by implementing StockObserver to receive real-time price notifications. It also has a method to receive order status updates.

Order

A central class representing a single trade request.

Order

It contains all details of the order, including the user, stock, type, and quantity. It acts as the Context for the State pattern, delegating cancellation logic to its currentState object.

StockExchange (Singleton)

The core engine of the system.

StockExchange

It maintains the order books (buy and sell orders) and contains the matching logic to execute trades when buy and sell orders align.

StockBrokerageSystem (Singleton & Facade)

The primary entry point for the application.

StockBrokerageSystem

It hides the system's internal complexity from the client and provides a simple, unified API for all major operations like registering users and placing orders.

3.2 Class Relationships

The relationships between classes define the system's structure and data flow.

Composition

  • A User "has-an" Account. The Account's lifecycle is managed by the User.

Association

  • An Order is associated with one User and one Stock.
  • An Order is associated with an ExecutionStrategy to determine its execution condition.
  • An Order has a current OrderState.
  • A Stock (Subject) is associated with a list of StockObservers (which are Users).

Inheritance

  • User implements the StockObserver interface.
  • BuyStockCommand and SellStockCommand implement the OrderCommand interface.
  • Concrete state classes (OpenState, etc.) implement the OrderState interface.
  • Concrete strategy classes (MarketOrderStrategy, etc.) implement the ExecutionStrategy interface.

Dependency

  • StockBrokerageSystem (Facade) depends on OrderCommand objects to place orders.
  • The OrderCommands depend on the StockExchange to submit the orders.
  • A client depends on the OrderBuilder to construct an Order object.
  • StockExchange depends on the ExecutionStrategy of an order to check if a trade can be made.

3.3 Key Design Patterns

Strategy Pattern

The ExecutionStrategy allows the logic for executing different order types (Market, Limit) to be encapsulated and made interchangeable.

ExecutionStrategy

The StockExchange can check if an order is executable without knowing the specific rules of that order type.

State Pattern

The lifecycle of an Order is managed using the State pattern. The Order (Context) delegates actions like cancel() to its current OrderState object.

OrderState

This cleanly separates state-specific logic (e.g., you can't cancel a Filled order) and makes the system robust.

Observer Pattern

This pattern is used to notify users of stock price changes. The Stock object (Subject) notifies all subscribed Users (Observers) whenever its price is updated, enabling real-time updates.

Command Pattern

The OrderCommand interface and its implementations (BuyStockCommand, SellStockCommand) encapsulate a request as an object.

OrderCommand

This decouples the client that initiates an order from the object that knows how to perform it (the StockExchange).

Builder Pattern

The OrderBuilder provides a fluent API for constructing complex Order objects. This is ideal for an object with multiple parameters, improving readability and ensuring that orders are created in a valid state.

Facade Pattern

The StockBrokerageSystem class serves as a facade. It provides a simple, high-level API (registerUser, placeBuyOrder) that hides the complex internal workflows involving accounts, order books, and the matching engine.

Singleton Pattern

StockBrokerageSystem and StockExchange are implemented as singletons. This ensures a single, globally accessible point of control for the entire application and for the central order book, preventing state inconsistencies.

3.4 Full Class Diagram

Online Stock Brokerage System Class Diagram

4. Implementation

4.1 Enums

1class OrderType(Enum):
2    MARKET = "MARKET"
3    LIMIT = "LIMIT"
4
5class TransactionType(Enum):
6    BUY = "BUY"
7    SELL = "SELL"
8
9class OrderStatus(Enum):
10    OPEN = "OPEN"
11    PARTIALLY_FILLED = "PARTIALLY_FILLED"
12    FILLED = "FILLED"
13    CANCELLED = "CANCELLED"
14    FAILED = "FAILED"
  • OrderType distinguishes between market and limit orders.
  • TransactionType indicates whether the action is a buy or sell.
  • OrderStatus tracks the lifecycle of an order.

4.2 Custom Exceptions

1class InsufficientFundsException(Exception):
2    def __init__(self, message: str):
3        super().__init__(message)
4
5class InsufficientStockException(Exception):
6    def __init__(self, message: str):
7        super().__init__(message)

These exceptions are thrown during trade validations:

  • InsufficientFundsException: not enough cash to buy.
  • InsufficientStockException: not enough stock to sell.

4.3 Account

1class Account:
2    def __init__(self, initial_cash: float):
3        self.balance = initial_cash
4        self.portfolio: Dict[str, int] = {}  # Stock symbol -> quantity
5        self.lock = threading.Lock()
6
7    def debit(self, amount: float) -> None:
8        with self.lock:
9            if self.balance < amount:
10                raise InsufficientFundsException(f"Insufficient funds to debit {amount}")
11            self.balance -= amount
12
13    def credit(self, amount: float) -> None:
14        with self.lock:
15            self.balance += amount
16
17    def add_stock(self, symbol: str, quantity: int) -> None:
18        with self.lock:
19            self.portfolio[symbol] = self.portfolio.get(symbol, 0) + quantity
20
21    def remove_stock(self, symbol: str, quantity: int) -> None:
22        with self.lock:
23            current_quantity = self.portfolio.get(symbol, 0)
24            if current_quantity < quantity:
25                raise InsufficientStockException(f"Not enough {symbol} stock to sell.")
26            self.portfolio[symbol] = current_quantity - quantity
27
28    def get_balance(self) -> float:
29        return self.balance
30
31    def get_portfolio(self) -> Dict[str, int]:
32        return self.portfolio.copy()
33
34    def get_stock_quantity(self, symbol: str) -> int:
35        return self.portfolio.get(symbol, 0)

The Account class holds the user's cash balance and owned stocks. All operations are thread-safe via synchronized to ensure consistency in concurrent environments.

4.4 Stock and Observer Pattern

StockObserver

Implements the Observer Pattern. Users are notified when stock prices change.

1class StockObserver(ABC):
2    @abstractmethod
3    def update(self, stock: 'Stock') -> None:
4        pass
1class Stock:
2    def __init__(self, symbol: str, initial_price: float):
3        self.symbol = symbol
4        self.price = initial_price
5        self.observers: List[StockObserver] = []
6
7    def get_symbol(self) -> str:
8        return self.symbol
9
10    def get_price(self) -> float:
11        return self.price
12
13    def set_price(self, new_price: float) -> None:
14        if self.price != new_price:
15            self.price = new_price
16            self._notify_observers()
17
18    def add_observer(self, observer: StockObserver) -> None:
19        self.observers.append(observer)
20
21    def remove_observer(self, observer: StockObserver) -> None:
22        if observer in self.observers:
23            self.observers.remove(observer)
24
25    def _notify_observers(self) -> None:
26        for observer in self.observers:
27            observer.update(self)

4.5 User

Each User holds an Account and receives stock price and order status updates. Acts as an observer of stock price changes.

1class User(StockObserver):
2    def __init__(self, name: str, initial_cash: float):
3        self.user_id = str(uuid.uuid4())
4        self.name = name
5        self.account = Account(initial_cash)
6
7    def get_user_id(self) -> str:
8        return self.user_id
9
10    def get_name(self) -> str:
11        return self.name
12
13    def get_account(self) -> Account:
14        return self.account
15
16    def update(self, stock: Stock) -> None:
17        print(f"[Notification for {self.name}] Stock {stock.get_symbol()} price updated to: ${stock.get_price():.2f}")
18
19    def order_status_update(self, order: 'Order') -> None:
20        print(f"[Order Notification for {self.name}] Order {order.get_order_id()} for {order.get_stock().get_symbol()} is now {order.get_status().value}.")
21

4.6 Order and State Pattern

Uses the State Pattern to allow state-specific behavior for cancel().

1class Order:
2    def __init__(self, order_id: str, user: User, stock: Stock, order_type: OrderType, 
3                 quantity: int, price: float, execution_strategy: ExecutionStrategy, owner: User):
4        self.order_id = order_id
5        self.user = user
6        self.stock = stock
7        self.type = order_type
8        self.quantity = quantity
9        self.price = price  # Limit price for Limit orders
10        self.execution_strategy = execution_strategy
11        self.owner = owner
12        self.current_state = OpenState()  # Initial state
13        self.status = OrderStatus.OPEN
14
15    def cancel(self) -> None:
16        self.current_state.cancel(self)
17
18    def get_order_id(self) -> str:
19        return self.order_id
20
21    def get_user(self) -> User:
22        return self.user
23
24    def get_stock(self) -> Stock:
25        return self.stock
26
27    def get_type(self) -> OrderType:
28        return self.type
29
30    def get_quantity(self) -> int:
31        return self.quantity
32
33    def get_price(self) -> float:
34        return self.price
35
36    def get_status(self) -> OrderStatus:
37        return self.status
38
39    def get_execution_strategy(self) -> ExecutionStrategy:
40        return self.execution_strategy
41
42    def set_state(self, state: OrderState) -> None:
43        self.current_state = state
44
45    def set_status(self, status: OrderStatus) -> None:
46        self.status = status
47        self._notify_owner()
48
49    def _notify_owner(self) -> None:
50        if self.owner:
51            self.owner.order_status_update(self)

4.7 Order Builder Pattern

Provides a fluent API to construct complex Order objects step-by-step.

1class OrderBuilder:
2    def __init__(self):
3        self.user: Optional[User] = None
4        self.stock: Optional[Stock] = None
5        self.type: Optional[OrderType] = None
6        self.transaction_type: Optional[TransactionType] = None
7        self.quantity: int = 0
8        self.price: float = 0.0
9
10    def for_user(self, user: User) -> 'OrderBuilder':
11        self.user = user
12        return self
13
14    def with_stock(self, stock: Stock) -> 'OrderBuilder':
15        self.stock = stock
16        return self
17
18    def buy(self, quantity: int) -> 'OrderBuilder':
19        self.transaction_type = TransactionType.BUY
20        self.quantity = quantity
21        return self
22
23    def sell(self, quantity: int) -> 'OrderBuilder':
24        self.transaction_type = TransactionType.SELL
25        self.quantity = quantity
26        return self
27
28    def at_market_price(self) -> 'OrderBuilder':
29        self.type = OrderType.MARKET
30        self.price = 0  # Not needed for market order
31        return self
32
33    def with_limit(self, limit_price: float) -> 'OrderBuilder':
34        self.type = OrderType.LIMIT
35        self.price = limit_price
36        return self
37
38    def build(self) -> Order:
39        execution_strategy = MarketOrderStrategy() if self.type == OrderType.MARKET else LimitOrderStrategy(self.transaction_type)
40        return Order(
41            str(uuid.uuid4()),
42            self.user,
43            self.stock,
44            self.type,
45            self.quantity,
46            self.price,
47            execution_strategy,
48            self.user
49        )

4.8 OrderCommand

Encapsulates buy/sell operations using the Command Pattern to decouple order placement from the execution logic.

1class OrderCommand(ABC):
2    @abstractmethod
3    def execute(self) -> None:
4        pass
5
6class BuyStockCommand(OrderCommand):
7    def __init__(self, account: Account, order: Order):
8        self.account = account
9        self.order = order
10        self.stock_exchange = StockExchange.get_instance()
11
12    def execute(self) -> None:
13        # For market order, we can't pre-check funds perfectly.
14        # For limit order, we can pre-authorize the amount.
15        estimated_cost = self.order.get_quantity() * self.order.get_price()
16        if self.order.get_type() == OrderType.LIMIT and self.account.get_balance() < estimated_cost:
17            raise InsufficientFundsException("Not enough cash to place limit buy order.")
18        print(f"Placing BUY order {self.order.get_order_id()} for {self.order.get_quantity()} shares of {self.order.get_stock().get_symbol()}.")
19        self.stock_exchange.place_buy_order(self.order)
20
21class SellStockCommand(OrderCommand):
22    def __init__(self, account: Account, order: Order):
23        self.account = account
24        self.order = order
25        self.stock_exchange = StockExchange.get_instance()
26
27    def execute(self) -> None:
28        if self.account.get_stock_quantity(self.order.get_stock().get_symbol()) < self.order.get_quantity():
29            raise InsufficientStockException("Not enough stock to place sell order.")
30        print(f"Placing SELL order {self.order.get_order_id()} for {self.order.get_quantity()} shares of {self.order.get_stock().get_symbol()}.")
31        self.stock_exchange.place_sell_order(self.order)

4.9 State

Implements the State Pattern for each valid OrderStatus, restricting transitions (e.g., filled orders can't be cancelled).

1class OrderState(ABC):
2    @abstractmethod
3    def handle(self, order: 'Order') -> None:
4        pass
5
6    @abstractmethod
7    def cancel(self, order: 'Order') -> None:
8        pass
9
10class OpenState(OrderState):
11    def handle(self, order: 'Order') -> None:
12        print("Order is open and waiting for execution.")
13
14    def cancel(self, order: 'Order') -> None:
15        order.set_status(OrderStatus.CANCELLED)
16        order.set_state(CancelledState())
17        print(f"Order {order.get_order_id()} has been cancelled.")
18
19class FilledState(OrderState):
20    def handle(self, order: 'Order') -> None:
21        print("Order is already filled.")
22
23    def cancel(self, order: 'Order') -> None:
24        print("Cannot cancel a filled order.")
25
26class CancelledState(OrderState):
27    def handle(self, order: 'Order') -> None:
28        print("Order is cancelled.")
29
30    def cancel(self, order: 'Order') -> None:
31        print("Order is already cancelled.")

4.10 ExecutionStrategy

Encapsulates different execution rules using the Strategy Pattern. This cleanly separates decision logic for market vs. limit orders.

1class ExecutionStrategy(ABC):
2    @abstractmethod
3    def can_execute(self, order: 'Order', market_price: float) -> bool:
4        pass
5
6class LimitOrderStrategy(ExecutionStrategy):
7    def __init__(self, transaction_type: TransactionType):
8        self.type = transaction_type
9
10    def can_execute(self, order: 'Order', market_price: float) -> bool:
11        if self.type == TransactionType.BUY:
12            # Buy if market price is less than or equal to limit price
13            return market_price <= order.get_price()
14        else:  # SELL
15            # Sell if market price is greater than or equal to limit price
16            return market_price >= order.get_price()
17
18class MarketOrderStrategy(ExecutionStrategy):
19    def can_execute(self, order: 'Order', market_price: float) -> bool:
20        return True  # Market orders can always execute

4.11 StockExchange

Implements the order matching engine. Supports atomic trade execution and uses synchronized blocks to ensure consistency.

1class StockExchange:
2    _instance: Optional['StockExchange'] = None
3    _lock = threading.Lock()
4
5    def __new__(cls):
6        if cls._instance is None:
7            with cls._lock:
8                if cls._instance is None:
9                    cls._instance = super().__new__(cls)
10        return cls._instance
11
12    def __init__(self):
13        if hasattr(self, 'initialized'):
14            return
15        self.buy_orders: Dict[str, List[Order]] = defaultdict(list)
16        self.sell_orders: Dict[str, List[Order]] = defaultdict(list)
17        self.match_lock = threading.Lock()
18        self.initialized = True
19
20    @classmethod
21    def get_instance(cls) -> 'StockExchange':
22        return cls()
23
24    def place_buy_order(self, order: Order) -> None:
25        self.buy_orders[order.get_stock().get_symbol()].append(order)
26        self._match_orders(order.get_stock())
27
28    def place_sell_order(self, order: Order) -> None:
29        self.sell_orders[order.get_stock().get_symbol()].append(order)
30        self._match_orders(order.get_stock())
31
32    def _match_orders(self, stock: Stock) -> None:
33        with self.match_lock:  # Critical section to prevent race conditions during matching
34            buys = self.buy_orders.get(stock.get_symbol(), [])
35            sells = self.sell_orders.get(stock.get_symbol(), [])
36
37            if not buys or not sells:
38                return
39
40            match_found = True
41            while match_found:
42                match_found = False
43                best_buy = self._find_best_buy(buys)
44                best_sell = self._find_best_sell(sells)
45
46                if best_buy and best_sell:
47                    buy_price = stock.get_price() if best_buy.get_type() == OrderType.MARKET else best_buy.get_price()
48                    sell_price = stock.get_price() if best_sell.get_type() == OrderType.MARKET else best_sell.get_price()
49
50                    if buy_price >= sell_price:
51                        self._execute_trade(best_buy, best_sell, sell_price)  # Trade at the seller's asking price
52                        match_found = True
53
54    def _execute_trade(self, buy_order: Order, sell_order: Order, trade_price: float) -> None:
55        print(f"--- Executing Trade for {buy_order.get_stock().get_symbol()} at ${trade_price:.2f} ---")
56
57        buyer = buy_order.get_user()
58        seller = sell_order.get_user()
59
60        trade_quantity = min(buy_order.get_quantity(), sell_order.get_quantity())
61        total_cost = trade_quantity * trade_price
62
63        # Perform transaction
64        buyer.get_account().debit(total_cost)
65        buyer.get_account().add_stock(buy_order.get_stock().get_symbol(), trade_quantity)
66
67        seller.get_account().credit(total_cost)
68        seller.get_account().remove_stock(sell_order.get_stock().get_symbol(), trade_quantity)
69
70        # Update orders
71        self._update_order_status(buy_order, trade_quantity)
72        self._update_order_status(sell_order, trade_quantity)
73
74        # Update stock's market price to last traded price
75        buy_order.get_stock().set_price(trade_price)
76
77        print("--- Trade Complete ---")
78
79    def _update_order_status(self, order: Order, quantity_traded: int) -> None:
80        # This is a simplified update logic. A real system would handle partial fills.
81        order.set_status(OrderStatus.FILLED)
82        order.set_state(FilledState())
83        stock_symbol = order.get_stock().get_symbol()
84        
85        # Remove from books
86        if order in self.buy_orders[stock_symbol]:
87            self.buy_orders[stock_symbol].remove(order)
88        if order in self.sell_orders[stock_symbol]:
89            self.sell_orders[stock_symbol].remove(order)
90
91    def _find_best_buy(self, buys: List[Order]) -> Optional[Order]:
92        open_orders = [o for o in buys if o.get_status() == OrderStatus.OPEN]
93        if not open_orders:
94            return None
95        return max(open_orders, key=lambda o: o.get_price())  # Highest limit price is best
96
97    def _find_best_sell(self, sells: List[Order]) -> Optional[Order]:
98        open_orders = [o for o in sells if o.get_status() == OrderStatus.OPEN]
99        if not open_orders:
100            return None
101        return min(open_orders, key=lambda o: o.get_price())  # Lowest limit price is best

4.12 StockBrokerageSystem

Acts as a Facade for the entire brokerage system. Encapsulates user registration, stock management, and order processing.

1class StockBrokerageSystem:
2    _instance: Optional['StockBrokerageSystem'] = None
3    _lock = threading.Lock()
4
5    def __new__(cls):
6        if cls._instance is None:
7            with cls._lock:
8                if cls._instance is None:
9                    cls._instance = super().__new__(cls)
10        return cls._instance
11
12    def __init__(self):
13        if hasattr(self, 'initialized'):
14            return
15        self.users: Dict[str, User] = {}
16        self.stocks: Dict[str, Stock] = {}
17        self.initialized = True
18
19    @classmethod
20    def get_instance(cls) -> 'StockBrokerageSystem':
21        return cls()
22
23    def register_user(self, name: str, initial_amount: float) -> User:
24        user = User(name, initial_amount)
25        self.users[user.get_user_id()] = user
26        return user
27
28    def add_stock(self, symbol: str, initial_price: float) -> Stock:
29        stock = Stock(symbol, initial_price)
30        self.stocks[stock.get_symbol()] = stock
31        return stock
32
33    def place_buy_order(self, order: Order) -> None:
34        user = order.get_user()
35        command = BuyStockCommand(user.get_account(), order)
36        command.execute()
37
38    def place_sell_order(self, order: Order) -> None:
39        user = order.get_user()
40        command = SellStockCommand(user.get_account(), order)
41        command.execute()
42
43    def cancel_order(self, order: Order) -> None:
44        order.cancel()

StockBrokerageSystemDemo

The demo class simulates user actions to validate the system.

1def print_account_status(user: User) -> None:
2    print(f"Member: {user.get_name()}, Cash: ${user.get_account().get_balance():.2f}, Portfolio: {user.get_account().get_portfolio()}")
3
4def stock_brokerage_system_demo():
5    # System Setup
6    system = StockBrokerageSystem.get_instance()
7
8    # Create Stocks
9    apple = system.add_stock("AAPL", 150.00)
10    google = system.add_stock("GOOG", 2800.00)
11
12    # Create Members (Users)
13    alice = system.register_user("Alice", 20000.00)
14    bob = system.register_user("Bob", 25000.00)
15
16    # Bob already owns some Apple stock
17    bob.get_account().add_stock("AAPL", 50)
18
19    # Members subscribe to stock notifications (Observer Pattern)
20    apple.add_observer(alice)
21    google.add_observer(alice)
22    apple.add_observer(bob)
23
24    print("--- Initial State ---")
25    print_account_status(alice)
26    print_account_status(bob)
27
28    print("\n--- Trading Simulation Starts ---\n")
29
30    # SCENARIO 1: Limit Order Match
31    print("--- SCENARIO 1: Alice places a limit buy, Bob places a limit sell that matches ---")
32
33    # Alice wants to buy 10 shares of AAPL if the price is $150.50 or less
34    alice_buy_order = OrderBuilder() \
35        .for_user(alice) \
36        .buy(10) \
37        .with_stock(apple) \
38        .with_limit(150.50) \
39        .build()
40    system.place_buy_order(alice_buy_order)
41
42    # Bob wants to sell 20 of his shares if the price is $150.50 or more
43    bob_sell_order = OrderBuilder() \
44        .for_user(bob) \
45        .sell(20) \
46        .with_stock(apple) \
47        .with_limit(150.50) \
48        .build()
49    system.place_sell_order(bob_sell_order)
50
51    # The exchange will automatically match and execute this trade.
52    # Let's check the status after the trade.
53    time.sleep(0.1)  # Give time for notifications to print
54    print("\n--- Account Status After Trade 1 ---")
55    print_account_status(alice)
56    print_account_status(bob)
57
58    # SCENARIO 2: Price Update triggers notifications
59    print("\n--- SCENARIO 2: Market price of GOOG changes ---")
60    google.set_price(2850.00)  # Alice will get a notification
61
62    # SCENARIO 3: Order Cancellation (State Pattern)
63    print("\n--- SCENARIO 3: Alice places an order and then cancels it ---")
64    alice_cancel_order = OrderBuilder() \
65        .for_user(alice) \
66        .buy(5) \
67        .with_stock(google) \
68        .with_limit(2700.00) \
69        .build()  # Price is too low, so it won't execute immediately
70    system.place_buy_order(alice_cancel_order)
71
72    print(f"Order status before cancellation: {alice_cancel_order.get_status().value}")
73    system.cancel_order(alice_cancel_order)
74    print(f"Order status after cancellation attempt: {alice_cancel_order.get_status().value}")
75
76    # Now try to cancel an already filled order
77    print("\n--- Trying to cancel an already FILLED order (State Pattern) ---")
78    print(f"Bob's sell order status: {bob_sell_order.get_status().value}")
79    system.cancel_order(bob_sell_order)  # This should fail
80    print(f"Bob's sell order status after cancel attempt: {bob_sell_order.get_status().value}")
81
82
83if __name__ == "__main__":
84    stock_brokerage_system_demo()

5. Run and Test

Files24
builder
commands
entities
enums
exceptions
observer
states
strategies
stock_brokerage_system_demo.py
main
stock_brokerage_system.py
stock_exchange.py
stock_brokerage_system_demo.pymain
Output

6. Quiz

Design Online Stock Exchange - Quiz

1 / 20
Multiple Choice

Which entity is responsible for matching buy and sell orders in the online stock exchange design?

How helpful was this article?

Comments


0/2000

No comments yet. Be the first to comment!

Copilot extension content script